<template>
	<view class="">
		<div id="myVideo" ref="myVideo"></div>
	</view>
</template>

<script>
	import vapi from '@/api/index.js';
	import config from '@/config';
	import Player from 'xgplayer';
	var graceJs = require('@/utils/grace.js');
	export default {
		name: 'kvideo',
		props: ['query'],
		data() {
			return {
				rqTime: 0, // 请求时间
				beyond: 2, // 超出 1S 进度拉回
				isLogin: config.isLogin(),
				videoContext: null,
				freeTime: 360, // 试看秒数 6分钟
				pant: 110, // 心跳秒数
				learningToken: '', // 学习token
				playStatus: '',
				learnSum: 0, // 累计提交
				learnTime: 0, // 阶段学习时长
				pTime: 0, // 播放器的播放时长，
				learnStatus: 0, // 0 未学 1 未学完 2 学完 整个课程的状态
				studentInfo: {
					learnStatus: 0, // 1 在学 2 学习完成
				},
				params: {},
				timer: null,
				flag: false,
				isRedis: false,
				isStart: false,
				handCheck: false,
				isSeek: false,
				isPlay: false,
				drag: false,
			};
		},

		computed: {
			// 视频学习状态 1试看 2学习(开始/继续) 3回看
			// learnStatus 0 未学 1 未学完 2 学完 整个课程的状态 courseStatus
			// studentInfo learnLength (已学长度) learnStatus 1(已购买未学完) 2(已购买已学完)
			learnStaus() {
				if (!this.isLogin || !this.learnStatus || !this.params.classesId || this.params.courseStatus == 2) {
					return 1;
				} else if (this.studentInfo.learnStatus == 1) {
					return 2;
				} else if (this.studentInfo.learnStatus == 2) {
					return 3;
				}
			},
		},

		methods: {
			// 播放
			async playerAudio(l, s, p) {

				this.learnStatus = l;
				this.studentInfo = JSON.parse(JSON.stringify(s));
				let temp = JSON.parse(JSON.stringify(p));
				if (escape(temp.url).indexOf('%u') >= 0) {
					temp.url = encodeURI(temp.url);
				}
				this.params = temp;
				this.learnSum = 0;
				this.pTime = parseInt(this.params.learnLength * 1);
				this.handCheck = true;
				this.isSeek = false;
				this.isPlay = false;
				this.drag = p.demandLength != p.learnLength;
				if (this.videoContext) {
					this.videoContext.config.disableProgress = this.drag;
				} else {
					await this.$nextTick();
					this.videoContext = new Player({
						id: 'myVideo',
						url: p.url,
						poster: p.poster,
						// 'time': params.demandLength * 1,
						'x5-video-player-type': 'h5', //微信同层播放
						'x5-video-player-fullscreen': false,
						playsinline: false,
						'webkit-playsinlin': false,
						'picture-in-picture-mode': [],
						'show-background-playback-button': false,
						autoplay: false,
						fluid: true,
						defaultPlaybackRate: 1,
						lang: 'zh-cn',
						closeVideoClick: true,
						closeVideoTouch: true,
						// lastPlayTime: params.learnLength * 1,
						lastPlayTimeHideDelay: 5, //提示文字展示时长（单位：秒）
						keyShortcut: 'off',
						//使移动端支持双击暂停/播放
						enableVideoDbltouch: true,
						height: 370,
						miniplayer: false,
						pip: false,
						//支持进度条只能拖动到已播过部分（播放器被接管或劫持时无效，比如iOS或安卓部分环境下）
						// allowSeekPlayed: _this.isLogin && params.classesId
						disableProgress: this.drag //禁止进度条拖动交互
					});
				}
				this.videoContext.on('play', e => {
					if (!this.params.url || this.isPlay) return;
					this.isPlay = true;
					this.isStart = true;
					this.handCheck = false;
					this.checkPlayStatus('play');
				});

				this.videoContext.on('pause', e => {
					if (this.playStatus == 'ended' || this.handCheck) return;
					this.isPlay = false;
					this.checkPlayStatus('pause', e.currentTime);
				});

				this.videoContext.on('ended', e => {
					if (!e) return;
					console.log('ended', e)
					this.isPlay = false;
					this.checkPlayStatus('ended', e.currentTime);
				});

				this.videoContext.on('playbackrateChange', e => {
					if (!e) return;
					this.videoContext.reload();
					that.go();
				});

				this.videoContext.on('canplay', e => {
					if (this.learnStaus == 2 && !this.isStart) {
						this.videoContext.currentTime = this.pTime * 1;
						this.isStart = true;
					}
				});

				this.videoContext.on('error', e => {
					if (!e) return;
					console.log(e)
				});

				// 监听进入全屏状态
				this.videoContext.on('requestFullscreen', e => {
					this.isFullscreen = true;
				});

				// 监听退出全屏状态
				this.videoContext.on('exitFullscreen', e => {
					this.isFullscreen = true;
				});

				this.videoContext.on('timeupdate', e => {
					if (this.isSeek || this.handCheck) return;
					this.checkPlayStatus('timeupdate', e.currentTime);
					this.isStart = true;
				});
				this.videoContext.src = this.params.url;
				this.videoContext.poster = this.params.poster;
				await this.sleep(500);
				// this.videoContext.currentTime = this.pTime;
				this.videoContext.start(this.params.url);
				this.videoContext.play();
			},

			// 播放状态处理
			async checkPlayStatus(type, e) {
				let {
					videoContext,
					pant,
					freeTime,
					pTime,
					learnSum,
					query,
				} = this;
				this.playStatus = type;
				if (!this.params.url) {
					return;
				}

				if (type == 'play') {
					if (this.learnStaus != 2) return;
					this.handledBefor(0, false, 'p1');
					return;
				}

				if (type == 'timeupdate') {
					if (this.learnStaus == 1) {
						let v = this.reduce([e, this.pTime], false);
						if (v > this.freeTime) {
							this.freePlayOver();
						}
					}
					if (this.learnStaus == 2) {
						if (e < this.pTime) return;
						this.learnTime = this.reduce([this.reduce([e, this.pTime], false), this.learnTime]);
						this.pTime = e;
						let sum = this.reduce([this.params.learnLength, this.learnSum, this.learnTime]);
						if (this.learnTime >= pant && sum <= this.params.demandLength) {
							this.handledBefor(this.learnTime, false, 't2');
							this.learnTime = 0;
						}
					}
				}

				if (type == 'pause') {
					await this.sleep(100)
					if (this.learnStaus == 2 && this.playStatus == 'pause') {
						if (this.learnTime > 1) {
							this.handledBefor(this.learnTime, false, 'p3');
							this.learnTime = 0;
						}
					}
				}

				if (type == 'ended') {
					if (this.learnStaus == 1) {
						this.freePlayOver();
						return;
					}

					if (this.learnStaus == 2) {
						let max = this.params.demandLength;
						let s1 = this.reduce([this.params.learnLength, this.learnSum]);
						let value = this.reduce([max, s1], false);
						if (value) this.handledBefor(value, true, 'e4');
					}

					if (this.learnStaus == 3) {
						this.changeNextNode();
					}
				}
			},

			handledBefor(len, next, o) {
				let v = 2000 - (this.getTime() - this.rqTime);
				if (this.isRedis) {
					this.isRedis = false;
					if (v > 0) {
						this.sleep(v).then(() => {
							this.heartbeatApi(Math.ceil(len), next);
						})
					} else {
						this.heartbeatApi(Math.ceil(len), next);
					}
				}
				let learnLength = this.params.learnLength;
				console.log('心跳', this.playStatus, len, this.pTime, learnLength, this.learnSum, this.isRedis, o);
			},

			async setSeek(v, t = true, e) {
				this.isSeek = true;
				await this.$nextTick();
				let {
					learnLength,
					demandLength
				} = this.params;

				if (v == 'sum') {
					v = this.reduce([learnLength, this.learnSum]);
					this.learnTime = 0;
				} else if (v > demandLength) {
					v = demandLength - 1;
				} else if (v < 0 || isNaN(v)) {
					v = 0;
				}
				v = parseInt(v)
				console.log('seek', e, this.playStatus, v, this.pTime, learnLength, this.learnSum, this.isRedis);

				if (v == 0 && this.playStatus == 'timeupdate') {
					this.videoContext.seek(v);
				} else if (v > 0 && v < demandLength) {
					this.videoContext.seek(v);
				}
				if (!t) {
					this.videoContext.pause();
				}
				this.isSeek = false;
			},

			go() {
				uni.redirectTo({
					url: `/pages/courseMarket/detail/index${this.query}&t=${new Date().getTime()}`
				});
			},

			// 退出全屏
			exitFullscreen() {
				if (this.videoContext.fullscreen) {
					this.videoContext.exitFullscreen(this.videoContext.root);
					this.videoContext.exitFullscreen();
				}
			},

			// 试看结束
			freePlayOver() {
				var szhy = config.storage(['user_info', 'szhy']);
				this.exitFullscreen();
				this.setSeek(this.freeTime, false);
				for (let i = 1; i < 100; i++) {
					clearInterval(i);
				}
				var that = this;
				var courseStatus = this.params.courseStatus;
				var msg = '试看结束，如需继续观看，请购买课程，是否加入购物车？';
				if (szhy == '01' || szhy == '11') {
					msg = '试看结束，如需继续观看，请前往课程超市进行购买，是否立即前往？';
				} else {
					if (courseStatus == 0) {
						msg = '试看结束，如需继续观看，请购买课程，课程已在购物车中，是否进入购物车去结算？';
					} else if (courseStatus == 2) {
						msg = '试看结束，如需继续观看，请购买课程，课程有存在支付中订单，是否继续支付？';
					}
				}
				that.setState();
				uni.showModal({
					title: '提示',
					content: msg,
					success: res => {
						if (res.confirm) {
							if (szhy == '01' || szhy == '11') {
								that.$uni.navigate(`/pages/courseMarket/index`, 'switchTab');
							} else {
								if (courseStatus == 0) {
									that.$uni.navigate(`/pages/shoppingCart/index`, 'switchTab');
								} else if (courseStatus == 2) {
									that.$uni.navigate(`/pagesA/order/index`, 'redirectTo');
								} else {
									that.$emit('handleShoppingCart');
								}
							}
						} else if (res.cancel) {}
					}
				});
			},

			// 心跳提交
			heartbeatApi(len, next = false) {
				this.learnSum = this.reduce([this.learnSum, len]);
				return new Promise(resolve => {
					this.learningToken = len == 0 ? '' : this.learningToken;
					this.$api.heartbeat({
							chapterId: this.params.chapterId,
							classesId: this.params.classesId,
							courseId: this.params.courseId,
							learningToken: this.learningToken,
							nodeId: this.params.nodeId,
							sourceType: 2,
							studentId: config.storage(['user_info', 'id']),
							viewingLength: len
						},
						e => {
							if (e.status == '0') {
								this.learningToken = e.data;
								let v = Math.ceil((this.pTime / this.params.demandLength) * 100);
								v = v > 100 ? 100 : v;
								this.$emit('updateProgress', v);
								if (next) this.changeNextNode(next);
							} else {
								if (e.status == 1 || e.status == 2) {
									uni.showModal({
										title: '提示',
										content: '网络延迟导致进度记录失败，请重新播放！',
										showCancel: false,
										confirmText: '确认',
										success: function(res) {
											if (res.confirm) {
												uni.navigateBack({
													delta: 2
												});
											}
										}
									});
								}
								if (e.data) {
									uni.showModal({
										title: '提示',
										content: e.data,
										showCancel: false
									});
								}
								this.setSeek('sum', true, '心跳提交报错');
							}
						},
						(e) => {
							if (e == 'request:fail timeout') {
								uni.showModal({
									title: '提示',
									content: `您的网络环境无法正常提交学时，请切换网络。`,
									showCancel: false,
									confirmText: '确认',
									success: function(res) {
										if (res.confirm) {
											uni.navigateBack({
												delta: 2
											});
										}
									}
								});
							} else {
								uni.showModal({
									title: '提示',
									content: `您的网络环境无法正常提交学时，请切换网络。`,
									confirmText: '确认',
									success: () => {
										uni.navigateBack({
											delta: 2
										});
									}
								});
							}
						},
						() => {
							if (this.playStatus != 'timeupdate') {
								this.learnTime = 0;
							}
							this.isRedis = true;
							this.rqTime = this.getTime();
						}
					);
				});
			},

			pause(t) {
				if (t) {
					if (this.videoContext) {
						this.videoContext.pause();
						uni.navigateBack({
							delta: 2
						});
					}
				} else {
					uni.navigateBack({
						delta: 2
					});
				}
			},

			// 请求更新当前节
			queryNewestStudent: function(next, resolve) {
				this.$emit('queryNewestStudent', this.params, this.params, next, resolve);
			},

			// 请求播放下一节
			changeNextNode: function() {
				this.$emit('changeNextNode', this.params.chapterId, this.params.nodeId);
			},

			getTime() {
				return new Date().getTime();
			},

			sleep(value = 30) {
				let timers;
				return new Promise(resolve => {
					setTimeout(() => {
						resolve();
						clearTimeout(timers);
					}, value);
				});
			},

			reduce(arr, t = true) {
				let x = 10000000000;
				let v = 0;
				if (t) {
					v = arr.reduce((pre, cur) => {
						return (pre * x + cur * x) / x;
					}, 0);
				} else {
					let f = arr.shift();
					v = arr.reduce((pre, cur) => {
						return (pre * x - cur * x) / x;
					}, f);
				}
				return v;
			},

			throttle(func, wait = 500, immediate = true) {
				if (!this.flag) {
					this.flag = true;
					typeof func === 'function' && func();
					this.timer = setTimeout(() => {
						this.flag = false;
						clearTimeout(this.timer);
					}, wait);
				}
			},
		},

		destroyed() {
			this.videoContext?.destroy();
		}
	};
</script>

<style scoped>
	.k-video {
		/* width: 750rpx;
		height: 230rpx;
		display: block;
		top: 0;
		left: 0;
		z-index: 900; */
	}

	.uni-video-cover {
		z-index: 901 !important;
	}

	.hideMe {
		display: none !important;
	}
</style>
